extends CharacterBody3D

signal health_changed(health_value)

const SPEED = 8
const JUMP_VELOCITY = 7
const FULL_HEALTH = 3
const RESPAWN_HEIGHT = 10

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var health = FULL_HEALTH

@onready var camera = $Camera3D
@onready var anim_player = $AnimationPlayer
@onready var muzzle_flash = $Camera3D/Pistol/MuzzleFlash
@onready var ray_cast = $Camera3D/RayCast3D


func _enter_tree():
	set_multiplayer_authority(str(name).to_int())


func _ready():
	if not is_multiplayer_authority():
		return

	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	camera.current = true


func _unhandled_input(event):
	if not is_multiplayer_authority():
		return

	if event is InputEventMouseMotion:
		rotate_y(-event.relative.x * .005)
		camera.rotate_x(-event.relative.y * .005)
		camera.rotation.x = clamp(camera.rotation.x, -PI / 2, PI / 2)

	if Input.is_action_just_pressed("shoot") and anim_player.current_animation != "Shoot":
		play_shoots_effects.rpc()
		if ray_cast.is_colliding():
			var hit_player = ray_cast.get_collider()
			hit_player.recieve_damage.rpc_id(hit_player.get_multiplayer_authority())


func _physics_process(delta):
	if not is_multiplayer_authority():
		return

	# Add the gravity.
	if not is_on_floor():
		velocity.y -= gravity * delta

	# Handle Jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var input_dir = Input.get_vector("left", "right", "up", "down")
	var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	if anim_player.current_animation == "Shoot":
		pass
	elif input_dir != Vector2.ZERO and is_on_floor():
		anim_player.play("Move")
	else:
		anim_player.play("Idle")

	move_and_slide()


@rpc("call_local") func play_shoots_effects():
	anim_player.stop()
	anim_player.play("Shoot")
	muzzle_flash.restart()
	muzzle_flash.emitting = true


@rpc("any_peer") func recieve_damage():
	health -= 1
	if health <= 0:
		health = FULL_HEALTH
		position = Vector3(0, RESPAWN_HEIGHT, 0)

	health_changed.emit(health)


func _on_animation_player_animation_finished(anim_name):
	if anim_name == "Shoot":
		anim_player.play("Idle")
